from django.conf import settings
from django.contrib.auth.backends import ModelBackend
import re

from django_redis import get_redis_connection

from apps.verifications.constants import MACHINE_TIMES_WAIT, MACHINE_TIMES
from .models import User


def get_user_by_account(account,mobile_flag):
    """
    根据account查询用户
    :param account: 用户名或者手机号
    :return: user
    """
    try:
        if mobile_flag and re.match('^1[3-9]\d{9}$', account):
            # 手机号登录
            user = User.objects.get(mobile=account)
        else:
            # 用户名登录
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileAuthBackend(ModelBackend):
    """自定义用户认证后端"""

    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        重写认证方法，实现多账号登录
        :param request: 请求对象
        :param username: 用户名
        :param password: 密码
        :param kwargs: 其他参数
        :return: user
        """
        # 根据传入的username获取user对象。username可以是手机号也可以是账号
        mobile_flag = 0  # 是否允许使用电话号码匹配,0表示优先使用电话号码匹配，如果失败，则认为是用户名，再次查询
        user = get_user_by_account(username,mobile_flag)
        # 校验user是否存在并校验密码是否正确
        if user and user.check_password(password):
            return user
        else:
            mobile_flag = 1
            user = get_user_by_account(username, mobile_flag)
            if user and user.check_password(password):
                return user
        return None


def generate_verify_email_url(user):
    """
    :param user: 用户对象
    :return:
    """
    # 1.加密的数据
    data_dict = {'user_id': user.id,"email": user.email}

    # 2. 进行加密数据
    from utils.secret import SecretOauth
    secret_data = SecretOauth().dumps(data_dict)

    # 3. 返回拼接url
    active_url = settings.EMAIL_ACTIVE_URL + '?token=' + secret_data
    return active_url


# 不允许出现恶意刷信息的用户，如果连续三次输入错误，就强行令其等待10s
def human_or_machine(mobile):
    redis_conn = get_redis_connection('send_flag_code')
    send_times = redis_conn.get('send_times_%s' % mobile)
    if send_times == 3:
        redis_conn.set('send_times_%s', MACHINE_TIMES_WAIT, 4)
    elif send_times > MACHINE_TIMES:
        # 认为是电脑
        return True
    else:
        redis_conn.setex('send_times_%s' % mobile, MACHINE_TIMES_WAIT, send_times + 1)
    return False
